#!/usr/local/bin/python
# Rob Dennis - Lurchington Q. Delacroix
# Keasby - TV renamer
# Project Homepage: http://code.google.com/p/keasby/

#--- Python Imports
import os

from os.path import join as pjoin

#--- Keasby Imports
import tv_episode
import keasby_toolbox
from keasby_base import KeasbyError
from keasby_options import kopt

from keasby_toolbox import log


class KeasbyInterpreter():
    """
    Parses information from existing files, and interacts with those files
    """

    def __init__(self):

        self.default_regex = self._init_regex()

    def interpret(self, path, regex=None):
        """
        Returns the interpreted information of a given path name in the form
        of a dictionary. Includes information about the path. Intended for use
        on a single file only.
        Optionally specify a regex for the manual interpretation of the
        path
        """

        if regex is None:
            regex = self.default_regex
        elif not isinstance(regex, InterpreterRegex):
            regex = InterpreterRegex(regex)

        if isinstance(path, tuple):
            #Handle split path case
            path = pjoin(path)

        if not isinstance(path, basestring):
            raise KeasbyInterpreterError("interpret method requires a string"+
                                            " %s provided"%type(path)+
                                            " . With value %s"%str(path))

        info_map = dict()

        info_map.update(self._init_path_info(path))
        info_map.update(self._regex_parse(info_map, regex))

##        try:
##            _tv_ep = tv_episode.TvEpisode(**info_map)
##        except tv_episode.TvEpisodeHasMultiplesError:
##            log.debug("splitting subepisodes in interpreter")
##            _tv_ep = self.split_sub_eps(info_map)
##
        return tv_episode.TvEpisodeFactory.new(**info_map)

##        return _tv_ep

##    @staticmethod
##    def split_sub_eps(info_map, split_char=kopt.cl_opts.split_episode_char):
##
##        import re
##
##        log.debug("attempting to split episode into subepisodes")
##
##        common_info_map = info_map.copy()
##        unique_dict = dict.fromkeys(tv_episode.TvEpisode.multi_attr, [])
##        counter_dict = {}
##
##        #TODO: Figure this out for more than 1 multiple
##        assert len(tv_episode.TvEpisode.multi_attr) == 1
##
##        for multiple in tv_episode.TvEpisode.multi_attr:
##            if multiple in info_map and split_char in info_map[multiple]:
##                del common_info_map[multiple]
##
##                for split_value in re.split(r".*%s"%split_char,
##                                                info_map[multiple]):
##
##                    log.debug("split using %s (%s) from string %s",
##                                    multiple, split_value, info_map[multiple])
##
##                    unique_dict[multiple].append((multiple, split_value))
##
##            else:
##                del unique_dict[multiple]
##
##        #TODO: Figure this out for more than 1 multiple
##        try:
##            sub_eps = [tv_episode.TvEpisode(**dict(episodenumber=unique))
##                        for unique in unique_dict["episodenumber"]]
##
##        except Exception as detail:
##            raise tv_episode.TvMultiEpisodeError("%s "%str(unique_dict) +
##                                                    str(detail))
##
##        return tv_episode.TvMultiEpisode(*sub_eps)

    @staticmethod
    def _init_regex():
        """
        Initialize the regular expression used to parse information
        """

        return InterpreterRegex()

    @staticmethod
    def _regex_parse(info_map, regex):

        return regex.parse(info_map)

    @staticmethod
    def _init_path_info(path):

        _fname, _ext = os.path.splitext(os.path.basename(path))
        _dir, _ = os.path.split(path)
        _pdir, _ = os.path.split(_dir)

        return dict(fname=_fname, ext=_ext, dir=_dir, path=path, pdir=_pdir)


class InterpreterRegex(object):
    """
    Controller for KeasbyInterpreter parsing via regular expressions
    """

    def __init__(self, *regexes):

        import re

        self.regex = []

        for regex in regexes:
            if isinstance(regex, basestring):

                try:
                    self.regex.append(re.compile(regex, re.IGNORECASE))
                except Exception, error_message:
                    raise InterpreterRegexError("error compiling regex:"+
                                                " %s"%regex+
                                                " message: %s"%error_message)


            elif isinstance(regex, InterpreterRegex):
                self.regex.append(regex)

            else:
                raise InterpreterRegexError("InterpreterRegex constructor"+
                                                " requires a string or unicode"+
                                                " object." +
                                                " %s provided"%type(regex))

    def parse(self, info_map, key="path"):
        """
        Method for deriving information from given information
        """

        for regex in self.regex:
            if isinstance(regex, InterpreterRegex):
                info_map.update(regex.parse(info_map))
            else:
                regex_match = regex.search(info_map[key])
                if regex_match:
                    info_map.update(regex_match.groupdict())
                else:
                    raise InterpreterRegexError(
                                            "using string: %s, "%regex.pattern+
                                            "and source: %s "%info_map[key]+
                                            "no match found" )

        return info_map


class KeasbyInterpreterError(KeasbyError):
    """
    KeasbyInterpreter Exception
    """


class InterpreterRegexError(KeasbyError):
    """
    InterpreterRegex Exception
    """


if __name__ == "__main__":
    pass